package ar.unc.famaf.pln.giveselector.selectors;

import java.io.*;
import java.util.*;

import ar.unc.famaf.pln.giveselector.context.*;

import give.formula.Atom;
import give.formula.Orientation;

/**
 * A DialogueSelector selects Utterances by picking those whose reaction match
 * the future planned acts
 * @author Luciana Benotti
 */
public class ACLSelector extends DefaultSelector
{
	protected static final int MAX_LENGTH_RESPONSE = 10;
	protected static final boolean DEBUG = true;

	/**
	 * Creates an DefaultComparisonSelector based on given File.
	 */
	public ACLSelector(File fileName)
	{
		super(fileName);
	}


	/**
	 * Creates an DefaultComparisonSelector based on given map of utterances.
	 */
	public ACLSelector(Map<String, Set<Utterance>> utterances)
	{
		super(utterances);
	}


	/**
	 * Selects the set of utterances whose response matches the next planned
	 * actions.
	 */
	@Override
	public Set<Utterance> selectUtterances(String worldName, Context context)
	{
		if (DEBUG)
		{
			System.out.println("==========================================");
			System.out.println("===== STARTING SELECTION");
		}

		Set<Utterance> selectedUtterances = new HashSet<Utterance>();
		if (!utterances.containsKey(worldName))
		{
			System.out.println(worldName + " is not supported by the NLG Server: supported worlds are "
					+ utterances.keySet());
			System.out.println(context.getFutureActions());
			return new HashSet<Utterance>();
		}

		int maxLengthResponse = Math.min(context.getFutureActions().size(), MAX_LENGTH_RESPONSE);
		for(Utterance candidate : utterances.get(worldName))
		{
			List<Atom> planResponse = candidate.getResponse().getDiscretizedActions();
			if (planResponse.size() > 0 || planResponse.size() <= maxLengthResponse)
				for(int i = 1; i <= maxLengthResponse; i++)
				{
					List<Atom> nPlannedActions = context.getNFutureAction(i);
					// In the case where the futureActions size in the context
					// object is equal to i and all the utterances match 
					// the following code will be executed
					// maxLengthResponse - i more times without need to. 
					if (planResponse.size() == nPlannedActions.size())
					{
						boolean allMatched = true;
						for(int j = 0; j < planResponse.size(); j++)
						{
							Atom responseAction = planResponse.get(j);
							Atom planAction = nPlannedActions.get(j);
							if (!responseAction.equals(planAction))
							{
								//System.out.println("Mismatch (j="+j+") : plan="+planAction+" response="+responseAction);
								allMatched = false;
								break;
							}
						}

						if (allMatched)
						{
							selectedUtterances.add(candidate);
							if (DEBUG)
							{
								System.out.println("Next " + i + " planned actions: " + nPlannedActions);
								System.out.println("[" + candidate.getId() + "] " + candidate.getText());
							}
							Context c1 = candidate.getContext();
							Orientation o2 = context.getOrientation();
							if (Math.abs(c1.getOrientation().getAngleTo(o2)) > (Math.PI / 4) && DEBUG)
								System.out.println("Different orientation");
							if (DEBUG)
								System.out.println("-----------------------------------");
						}
					}
				}
		}

		if (DEBUG)
		{
			System.out.println("==========================================");
			System.out.println("==========================================");
		}

		if (selectedUtterances.isEmpty() && DEBUG)
			System.out.println("No utterances for plan: " + context.getNFutureAction(10));
		return selectedUtterances;
	}


	/**
	 * Returns a List of Atoms where manipulate and manipulate-stateless are
	 * rewritten.
	 * @param plan
	 * @return
	 */
	public static List<Atom> cleanPlannerActions(List<Atom> plan)
	{
		List<Atom> ret = new ArrayList<Atom>();
		for(Atom action : plan)
			if (action.getPredicate().equals("manipulate") || action.getPredicate().equals("manipulate-stateless"))
			{
				Atom cleanManipulate = new Atom(action.getPredicate(), action.getArguments().get(0));
				ret.add(cleanManipulate);
			}
			else ret.add(action);
		return ret;
	}
}
